import * as Koa from 'koa';
import koaBody = require('koa-body');
import { Transaction } from 'tiny-entity2';
import { Guid, route, RouteOptionsVerify, ServiceManager, UsingLock } from "../../common";
import { ServiceException } from '../../common/excpetion';
import { ApiDataContext } from '../../domain/apiDataContext';
import { Department } from '../../domain/models/department';
import { OrganizationTree } from '../../domain/models/organizationTree';
import { DepartmentService } from '../../service/DepartmentService';
import { checkIsChildDep, OrganizationTreeService } from '../../service/organizationTreeService';
const departmentSvr = ServiceManager.Current.GetService<DepartmentService>('DepartmentService');
const orzTreeSvr = ServiceManager.Current.GetService<OrganizationTreeService>('OrganizationTreeService');

class DepartmentController {
    @route(new RouteOptionsVerify('GET', '/api/department'))
    async queryDepartments(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let params = ctx.query;
        params.organizationId = rootOrgId;

        let department = await departmentSvr.QueryDepartment(params);
        ctx.response.body = department;
        await next();
    }
    @route(new RouteOptionsVerify('GET', '/api/department/:id'))
    async getDepartmentInfoById(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let id = ctx.params.id;
        let data = await departmentSvr.GetDepartmentById(id);

        let orgtrees: OrganizationTree[] = await orzTreeSvr.QueryOrganizationTree({ organizationId: rootOrgId, objectName: data.ClassName(), objectId: id });
        data.orgTree = <OrganizationTree>{};
        if (orgtrees && orgtrees.length > 0) {
            data.orgTree = orgtrees[0];
        }

        ctx.response.body = data;
        await next();
    }
    @route(new RouteOptionsVerify('POST', '/api/department'))
    async createDepartment(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let department: Department = ctx.request.body;
        department.orgTree.organizationId = rootOrgId;
        checkData(department);

        department.id = Guid.GetGuid();
        department.isDelete = false;
        department.createTime = Date.now();
        department.modifyTime = Date.now();

        let orgTree = new OrganizationTree();
        orgTree.id = Guid.GetGuid();
        orgTree.isDelete = false;

        if (rootOrgId) {
            orgTree.organizationId = rootOrgId;
        }

        await Transaction(new ApiDataContext(), async datactx => {
            let result = await departmentSvr.CreateDepartment(department, datactx);
            orgTree.objectId = result.id;
            orgTree.objectName = result.ClassName();
            orgTree.nodeName = result.name;
            orgTree.parentId = department.orgTree.parentId;


            result.orgTree = await orzTreeSvr.CreateorganizationTree(orgTree, datactx);

            //更改部门负责人所属部门
            if (result && result.leaderPerson
                && result.leaderPerson.length > 0
                && result.orgTree
                && result.orgTree.id
                && result.orgTree.id.length > 0) {
                let leaderTreeNode = await orzTreeSvr.QueryOrganizationTree({ objectId: result.leaderPerson });
                if (leaderTreeNode && leaderTreeNode.length > 0) {
                    leaderTreeNode[0].parentId = result.orgTree.id;
                    await orzTreeSvr.UpdateorganizationTree(leaderTreeNode[0], datactx);
                }
            }

            ctx.response.body = result;
        });

        await next();
    }
    @route(new RouteOptionsVerify('PUT', '/api/department'))
    async updateDepartment(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let department = <Department>ctx.request.body;
        if (!department.id) {
            throw new ServiceException('id 不能为空！', 'not_be_null');
        }
        department.orgTree.organizationId = rootOrgId;
        department.modifyTime = Date.now();
        checkData(department);
        await UsingLock(department.id, async () => {
            await Transaction(new ApiDataContext(), async datactx => {
                let depData = await departmentSvr.GetDepartmentById(department.id);

                depData.ConverToEntity(department);

                let result = await departmentSvr.UpdateDepartment(depData, datactx);

                let orgTreeDatas = await orzTreeSvr.QueryOrganizationTree({ objectId: department.id });

                if (orgTreeDatas && orgTreeDatas.length > 0) {
                    let orgTreeData = orgTreeDatas[0];

                    let currparentId = orgTreeData.parentId;
                    //判断当前 parentId 是否为 其子Id
                    let orgAllTreeData = await orzTreeSvr.QueryOrganizationTree({ "organizationId": rootOrgId, objectName: Department.name });
                    let dgresult: boolean = false;
                    checkIsChildDep(orgAllTreeData, orgTreeData.id, department.orgTree.parentId, function (b) {
                        dgresult = b;
                    });
                    if (dgresult) {
                        //将所有子节点，接到上级
                        orgAllTreeData.forEach(async x => {
                            if (x.parentId == orgTreeData.id) {
                                x.parentId = currparentId;
                                await orzTreeSvr.UpdateorganizationTree(x, datactx);
                            }
                        });
                    }

                    orgTreeData.parentId = department.orgTree.parentId ? department.orgTree.parentId : orgTreeData.parentId;
                    orgTreeData.nodeName = depData.name;
                    result.orgTree = await orzTreeSvr.UpdateorganizationTree(orgTreeData, datactx);
                }


                //更改部门负责人所属部门
                if (result && result.leaderPerson
                    && result.leaderPerson.length > 0
                    && result.orgTree
                    && result.orgTree.id
                    && result.orgTree.id.length > 0) {
                    let leaderTreeNode = await orzTreeSvr.QueryOrganizationTree({ objectId: result.leaderPerson });
                    if (leaderTreeNode && leaderTreeNode.length > 0) {
                        leaderTreeNode[0].parentId = result.orgTree.id;
                        await orzTreeSvr.UpdateorganizationTree(leaderTreeNode[0], datactx);
                    }
                }

                ctx.response.body = result;
            });
        })

        await next();
    }
    @route(new RouteOptionsVerify('DELETE', '/api/department/:id'))
    async deleteDepartment(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let id = ctx.params.id;
        if (!id) {
            throw new ServiceException('id 不能为空！', 'not_be_null');
        }
        let department = await departmentSvr.GetDepartmentById(id);
        if (!department) {
            throw new ServiceException('无部门信息');
        }
        department.isDelete = true;

        ctx.response.body = await UsingLock(department.id, async () => {
            return await Transaction(new ApiDataContext(), async datactx => {

                let result = departmentSvr.UpdateDepartment(department, datactx);

                let deptrees = await orzTreeSvr.QueryOrganizationTree({ objectId: department.id, organizationId: rootOrgId });

                if (deptrees && deptrees.length > 0) {
                    department.orgTree = deptrees[0];
                    orzTreeSvr.DeleteOrganizationTreeById(department.orgTree.id);
                }
                return department;
            })
        })
        await next();
    }

    async setDepartmentLeader(ctx: Koa.Context, next) {

    }
}

const checkData = (data: Department) => {
    if (!data.name) {
        throw new ServiceException('未填写部门名称！');
    }
    if (!data.organizationId) {
        throw new ServiceException('未传入所属组织编号！');
    }

    if (!data.orgTree.organizationId) {
        throw new ServiceException('未传入根组织编号！');
    }
}